package com.cong.security.core.social.app;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.cong.security.core.constant.SecurityConstant;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OpenIdAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    //默认openId参数名
    private String openIdParameter = SecurityConstant.DEFAULT_PARAMETER_NAME_OPENID;
    //默认clientId参数名(设备编号,解决用户未绑定手机号时根据设备编号在缓存中临时存储第三方信息)
    private String deviceIdParameter = SecurityConstant.DEFAULT_PARAMETER_NAME_DEVICEID;
    //默认登录方式参数名
    private String providerIdParameter = SecurityConstant.DEFAULT_PARAMETER_NAME_PROVIDERID;
    //默认accessToken参数名
    private String accessTokenParameter = SecurityConstant.DEFAULT_PARAMETER_NAME_ACCESS_TOKEN;

    private boolean postOnly = true;

    protected OpenIdAuthenticationFilter() {
        super(new AntPathRequestMatcher(SecurityConstant.DEFAULT_LOGIN_PROCESSING_URL_OPENID, "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String openId = obtainOpenId(request);
        String deviceId = obtainDeviceId(request);
        String providerId = obtainProviderId(request);
        log.info("封装三方[{}]用户[{}]来源于[{}]的信息", providerId, openId, deviceId);
        OpenIdAuthenticationToken authRequest = new OpenIdAuthenticationToken(openId, deviceId, providerId);
        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * 获取clientId
     */
    protected String obtainDeviceId(HttpServletRequest request) {
        String deviceId = request.getParameter(deviceIdParameter);
        if (deviceId == null) {
            deviceId = "";
        }
        return deviceId.trim();
    }

    /**
     * 获取openId
     */
    protected String obtainOpenId(HttpServletRequest request) {
        String openId = request.getParameter(openIdParameter);
        if (openId == null) {
            openId = "";
        }
        return openId.trim();
    }

    /**
     * 获取providerId
     */
    protected String obtainProviderId(HttpServletRequest request) {
        String providerId = request.getParameter(providerIdParameter);
        if (providerId == null) {
            providerId = "";
        }
        return providerId.trim();
    }

    protected void setDetails(HttpServletRequest request, OpenIdAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }
}
